import type { VNode } from 'vue'
import { createVNode, defineComponent, h, reactive, render } from 'vue'
import BeLoading from './BeLoading.vue'

interface LoadingProps {
  text: string
  loading: boolean
  fullscreen: boolean
  className: string | string[] | object | object[]
}

// 工具函数：创建编程式 Loading 实例
export const createLoading = (props?: Partial<LoadingProps>, target?: HTMLElement, wait = false) => {
  // 挂载的虚拟节点
  let vnode: VNode | null = null

  // 响应式数据源，控制传给组件的 props
  const data = reactive<LoadingProps>({
    text: '',
    loading: true,
    fullscreen: false,
    className: '',
    ...props
  })

  // 包装组件，渲染 BeLoading 并传递响应式数据
  const LoadingWrap = defineComponent({
    render() {
      return h(BeLoading, { ...data } as any)
    }
  })

  // 创建虚拟节点
  vnode = createVNode(LoadingWrap)

  // 创建一个挂载容器 div
  const container = document.createElement('div')

  // 挂载渲染函数
  const mount = () => {
    render(vnode!, container)
  }

  // 如果 wait = true，延迟挂载（用于组件树稳定后再挂）
  if (wait) {
    setTimeout(mount, 0)
  } else {
    mount()
  }

  // open：挂载到目标元素
  const open = (el: HTMLElement = document.body) => {
    if (!vnode || !vnode.el) return
    el.appendChild(vnode.el as HTMLElement)
  }

  // close：从 DOM 中移除组件
  const close = () => {
    if (vnode?.el && vnode.el.parentNode) {
      vnode.el.parentNode.removeChild(vnode.el)
    }
    render(null, container) // 卸载 vnode
    vnode = null
  }

  // 自动挂载（如果传入了 target）
  if (target) {
    open(target)
  }

  return {
    vnode,
    open,
    close,

    // 修改文案
    setText: (text: string) => {
      data.text = text
    },

    // 修改 loading 状态（比如关闭 spinner）
    setLoading: (loading: boolean) => {
      data.loading = loading
    }
  }
}
